﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Centido.Core
{
    /// <summary>
    ///   A container that stores all metadata installers.
    /// </summary>
    /// <remarks>This class helps to create an instance of a metadata installer
    /// using the name of the database vendor. That can be useful when writing
    /// a generic schema installer.</remarks>
    /// <example>
    ///   The following example shows how to get an installer for the specified database vendor.
    /// <code>
    ///     using System;
    ///     using Centido.Core;
    /// 
    ///     class DomainBuildSample
    ///     {
    ///         static void Main()
    ///         {
    ///             var installer = Installers.GetInstaller("SQLSERVER");
    /// 
    ///             //Creating an application user and an application database
    ///             installer.DbProviderName = "MSSQLSERVER";
    ///             installer.DbConnectionString = @"Data Source=.\SQLEXPRESS;User Id=sa;Password=P@ssw0rd;";
    ///             
    ///             installer.CreateAppUser("AppUser", "P@ssw0rd", "AppDb");
    /// 
    ///             //Installing the metadata (using the application user credentials)
    ///             installer.DbConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=AppDb;User Id=AppUser;Password=P@ssw0rd;";
    ///             
    ///             installer.Install();
    /// 
    ///             //Creating an administrator (using the application user credentials)
    ///             var domainConfig = new DomainConfiguration()
    ///             {
    ///                 DbConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=AppDb;User Id=AppUser;Password=P@ssw0rd;",
    ///                 DbProviderName = "MSSQLSERVER"
    ///             };
    ///         
    ///             var domain = Domain.Build(domainConfig);
    ///             
    ///             var admin = domain.AddUser("AppAdmin", "P@ssw0rd");
    /// 
    ///             admin.CanChangeSchema = true;
    ///             admin.CanChangeSecurity = true;
    ///         }
    ///     }
    /// </code>
    /// </example>
    public sealed class Installers
    {
        /// <summary>
        ///   A collection of all metadata installers.
        /// </summary>
        public static readonly ICollection<Installer> Instances
            = new List<Installer> {new SqlServerInstaller(), new OracleInstaller()};


        /// <summary>
        ///   Retrieves a metadata installer for the product of the specified name.
        /// </summary>
        /// <param name="productName">The name of the product.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="productName"/> is null.</exception>
        /// <exception cref="ArgumentException">Thrown when the value of <paramref name="productName"/> is an empty string.</exception>
        /// <returns>Returns a metadata installer for the product of the specified name if the one
        /// exists; otherwise, false.</returns>
        public static Installer GetInstaller(string productName)
        {
            if (productName == null)
                throw new ArgumentNullException("productName");
            if (productName.Trim().Length == 0)
                throw new ArgumentException("The product name cannot be empty.");

            productName = productName.Trim().ToUpper();

            return Instances.SingleOrDefault(i => i.ProductName == productName);
        }
    }
}
